﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Super_Pong.BaseClasses
{
    class Timer
    {

        #region Atributos
        private long time;
        private long maxTime;
        private long loops;
        private Boolean running;
        #endregion

        #region Constructors
        /// <summary>
        /// Cria um timer com os defaults (tempo = 0, loops = -1, maxTime = -1).</summary>
        public Timer()
            : this(0L, -1L, -1L)
        {}

        /// <summary>
        /// Cria o timer com um startTime.</summary>
        public Timer(long startTime)
            : this(startTime, -1L, -1L)
        {}

        /// <summary>
        /// Cria o timer com argumentos.</summary>
        /// <param name="startTime"> O tempo para o timer começar.</param>
        /// <param name="startLoops"> Quantos loops o timer vai realizar antes de parar.</param>
        /// <param name="maxTime"> Qual o tempo de cada loop.</param>
        public Timer(long startTime, long startLoops, long maxTime)
        {
            if (startTime > 0L && startTime < maxTime)
                time = startTime;
            else
                time = 0L;

            if(startLoops > 0L)
                loops = startLoops;

            if (maxTime > 0L)
                this.maxTime = maxTime;

            running = false;
        }
        #endregion

        #region Methods
        //Update this timer
        /// <summary>
        /// Update the timer.</summary>
        /// <param name="gameTime"> Pass the gameTime in order to have an acurrate time.</param>
        public void Update(GameTime gametime)
        {
            //Apenas atualiza se estiver rodando
            if (running)
            {
                //Se é loop-based ou se nao é (loops < 0) acrecenta no tempo
                if ((loops > 0L && time < maxTime) || loops < 0L)
                {
                    //Soma o delay do jogo (o tempo de cada iteração)
                    time += gametime.ElapsedGameTime.Milliseconds;
                }
                
                //Para o timer quando os loops chegam a 0 no caso de loop based
                if(loops == 0L)
                {
                    running = false;
                }

                //Tempo passa do limite => reseta o timer e retira um loop
                if (time >= maxTime && loops > 0L)
                {
                    time = 0L;
                    loops--;
                }
            }
        }

        //Roda o timer iniciando em um tempo determinado
        /// <summary>
        /// Inicia o timer apartir de um tempo t.</summary>
        /// <param name="startTime"> O tempo para o timer começar.</param>
        public void Run(long startTime)
        {
            //Evita comandos repetidos caso o timer ja esteja rodando
            if (!running)
            {
                //Apenas aceita o tempo se o mesmo for valido (entre 0 e maxTime)
                if (startTime < maxTime && startTime > 0L)
                {
                    time = startTime;
                }
                //Roda o timer
                running = true;
            }
        }

        //Roda o timer
        /// <summary>
        /// Roda o timer.</summary>
        public void Run()
        {
            //Evita repetiçao de comandos
            if(!running)
                running = true;
        }

        //Para o timer mas nao reseta
        /// <summary>
        /// Para o timer sem resetar.</summary>
        public void Pause()
        {
            running = false;
        }

        //Para e reseta o timer
        /// <summary>
        /// Para e reseta o timer.</summary>
        public void Stop()
        {
            running = false;
            Reset();
        }

        //Reseta sem parar o timer
        /// <summary>
        /// Reseta o timer sem parar ele.</summary>
        public void Reset()
        {
            time = 0L;
        }

        //Para reseta e mata os loops
        /// <summary>
        /// Reseta, para e remove os loops.</summary>
        public void FullReset()
        {
            Stop();
            loops = 0L;
        }
        #endregion

        #region getsAndSets
        //Time
        public long GetTime()
        {
            return time;
        }

        public void SetTime(long t)
        {
            //Rescebe o novo tempo e garante que seja valido
            if (t > 0L && t < maxTime)
                time = t;
        }

        //Max time
        public long GetMaxTime()
        {
            return maxTime;
        }

        public void SetMaxTime(long t)
        {
            //Apenas aceia tempos acima de 0 e reseta o timer quando é chamada
            if (t > 0L)
            {
                maxTime = t;
                time = 0L;
            }
        }

        //Loops
        public long GetLoops()
        {
            return loops;
        }

        public void SetLoops(long l)
        {
            //Apenas loops validos
            if(l>0L)
                loops = l;
        }
        #endregion
    }
}
